using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Media;
using Services;
using Utilities;

namespace AudioComponent
{
    public interface IAudioManager
    {

        void OnYellow1(float volume);

        void OnYellow2(float volume);

        void OnBlue1(float volume);

        void OnBlue2(float volume);

        void OnGreen1(float volume);

        void OnGreen2(float volume);

        void OnClick(float volume);

        void OnPlayClick(float volume);

        void OnBubbleWave(float volume);

        void OnDefeat(float volume);

        void OnTrashMaster(float volume);

        void OnAspirapolvere(float volume);

        void OnError(float volume);

        void OnBrokenSack(float volume);

        void OnFlick(float volume);

        void OnNo(float volume);

        void OnTerraColpita(float volume);

        void OnSoundTrackBegin(float volume);


        void stopAllSounds();

        void pauseAllSounds();

        void resumeAllSounds();

        void OnaudioOff();

        void OnaudioOn();

    }

    public class AudioManager : CameraConsumer, IAudioManager
    {
        protected SoundEffectInstance soundTrack;

        protected ArrayList<SoundEffectInstance>
            yellow1, yellow2, blue1, blue2, green1, green2, click, playClick, BubbleWave, Defeat,
            TrashMaster, Aspirapolvere, error, brokenSack, Flick, No, TerraColpita;


        static private float volume;

        static public float Volume
        {
            get { return volume; }
            set
            {
                volume = value;
            }
        }


        protected string 
            yellow1_p, yellow2_p, blue1_p, blue2_p, green1_p, green2_p, click_p, playClick_p, BubbleWave_p, Defeat_p,
            TrashMaster_p, Aspirapolvere_p, error_p, brokenSack_p, Flick_p, No_p, TerraColpita_p, soundTrack_p;

        public AudioManager(Microsoft.Xna.Framework.Game game)
            : base(game)
        {
            game.Services.AddService(typeof(IAudioManager), this);
            this.UpdateOrder = (int)ComponentOrders.SCENE;
            this.DrawOrder = (int)ComponentOrders.SCENE;

        }

        public override void Initialize()
        {
            string path = @"Audio/";

            yellow1_p = path + "CartaDef";
            yellow2_p = path + "NylonDef";
            blue1_p = path + "BottigliaDef";
            blue2_p = path + "Tin";
            green1_p = path + "Squash";
            green2_p = path + "SquashI";
            click_p = path + "Bip";
            playClick_p = path + "BipStart";
            BubbleWave_p = path + "Bubble";
            Defeat_p = path + "DefeatPlay";
            TrashMaster_p = path + "TrashMaster";
            Aspirapolvere_p = path + "VacumDef";
            Flick_p = path + "Flick";
            error_p = path + "Errors";
            brokenSack_p = path + "SacchettoBroken";
            No_p = path + "No";
            TerraColpita_p = path + "TerraColpita";
            
            soundTrack_p = path + "Music";


            soundTrack = Game.Content.Load<SoundEffect>(soundTrack_p).CreateInstance();

            yellow1 = new ArrayList<SoundEffectInstance>(3) 
                {
                    Game.Content.Load<SoundEffect>(yellow1_p).CreateInstance(),
                    Game.Content.Load<SoundEffect>(yellow1_p).CreateInstance(),
                    Game.Content.Load<SoundEffect>(yellow1_p).CreateInstance()
                };
            yellow2 = new ArrayList<SoundEffectInstance>(3) 
                {
                    Game.Content.Load<SoundEffect>(yellow2_p).CreateInstance(),
                    Game.Content.Load<SoundEffect>(yellow2_p).CreateInstance(),
                    Game.Content.Load<SoundEffect>(yellow2_p).CreateInstance()
                }
                ;
            blue1 = new ArrayList<SoundEffectInstance>(3)
                {
                    Game.Content.Load<SoundEffect>(blue1_p).CreateInstance(),
                    Game.Content.Load<SoundEffect>(blue1_p).CreateInstance(),
                    Game.Content.Load<SoundEffect>(blue1_p).CreateInstance()
                };

            blue2 = new ArrayList<SoundEffectInstance>(3)
                {
                    Game.Content.Load<SoundEffect>(blue2_p).CreateInstance(),
                    Game.Content.Load<SoundEffect>(blue2_p).CreateInstance(),
                    Game.Content.Load<SoundEffect>(blue2_p).CreateInstance()
                };
            green1 = new ArrayList<SoundEffectInstance>(3)
                {
                    Game.Content.Load<SoundEffect>(green1_p).CreateInstance(),
                    Game.Content.Load<SoundEffect>(green1_p).CreateInstance(),
                    Game.Content.Load<SoundEffect>(green1_p).CreateInstance()
                };
            green2 = new ArrayList<SoundEffectInstance>(3)
                {
                    Game.Content.Load<SoundEffect>(green2_p).CreateInstance(),
                    Game.Content.Load<SoundEffect>(green2_p).CreateInstance(),
                    Game.Content.Load<SoundEffect>(green2_p).CreateInstance()
                };
            click = new ArrayList<SoundEffectInstance>(3)
                {
                    Game.Content.Load<SoundEffect>(click_p).CreateInstance(),
                    Game.Content.Load<SoundEffect>(click_p).CreateInstance(),
                    Game.Content.Load<SoundEffect>(click_p).CreateInstance()
                };
            playClick = new ArrayList<SoundEffectInstance>(3)
                {
                    Game.Content.Load<SoundEffect>(playClick_p).CreateInstance(),
                    Game.Content.Load<SoundEffect>(playClick_p).CreateInstance(),
                    Game.Content.Load<SoundEffect>(playClick_p).CreateInstance()
                };
            BubbleWave = new ArrayList<SoundEffectInstance>(3)
                {
                    Game.Content.Load<SoundEffect>(BubbleWave_p).CreateInstance(),
                    Game.Content.Load<SoundEffect>(BubbleWave_p).CreateInstance(),
                    Game.Content.Load<SoundEffect>(BubbleWave_p).CreateInstance()
                };
            Defeat = new ArrayList<SoundEffectInstance>(3)
                {
                    Game.Content.Load<SoundEffect>(Defeat_p).CreateInstance(),
                    Game.Content.Load<SoundEffect>(Defeat_p).CreateInstance(),
                    Game.Content.Load<SoundEffect>(Defeat_p).CreateInstance()
                };
            Aspirapolvere = new ArrayList<SoundEffectInstance>(3)
                {
                    Game.Content.Load<SoundEffect>(Aspirapolvere_p).CreateInstance(),
                    Game.Content.Load<SoundEffect>(Aspirapolvere_p).CreateInstance(),
                    Game.Content.Load<SoundEffect>(Aspirapolvere_p).CreateInstance()
                };
            TrashMaster = new ArrayList<SoundEffectInstance>(3)
                {
                    Game.Content.Load<SoundEffect>(TrashMaster_p).CreateInstance(),
                    Game.Content.Load<SoundEffect>(TrashMaster_p).CreateInstance(),
                    Game.Content.Load<SoundEffect>(TrashMaster_p).CreateInstance()
                };
            error = new ArrayList<SoundEffectInstance>(3)
                {
                    Game.Content.Load<SoundEffect>(error_p).CreateInstance(),
                    Game.Content.Load<SoundEffect>(error_p).CreateInstance(),
                    Game.Content.Load<SoundEffect>(error_p).CreateInstance(),
                };
            brokenSack = new ArrayList<SoundEffectInstance>(3)
                {
                    Game.Content.Load<SoundEffect>(brokenSack_p).CreateInstance(),
                    Game.Content.Load<SoundEffect>(brokenSack_p).CreateInstance(),
                    Game.Content.Load<SoundEffect>(brokenSack_p).CreateInstance()
                };            
            Flick = new ArrayList<SoundEffectInstance>(3)
                {
                    Game.Content.Load<SoundEffect>(Flick_p).CreateInstance(),
                    Game.Content.Load<SoundEffect>(Flick_p).CreateInstance(),
                    Game.Content.Load<SoundEffect>(Flick_p).CreateInstance()                    
                };
            No = new ArrayList<SoundEffectInstance>(3)
                {
                    Game.Content.Load<SoundEffect>(No_p).CreateInstance(),                    
                    Game.Content.Load<SoundEffect>(No_p).CreateInstance(),                   
                    Game.Content.Load<SoundEffect>(No_p).CreateInstance()                    
                };
            TerraColpita = new ArrayList<SoundEffectInstance>(3)
                {
                    Game.Content.Load<SoundEffect>(TerraColpita_p).CreateInstance(),
                    Game.Content.Load<SoundEffect>(TerraColpita_p).CreateInstance(),
                    Game.Content.Load<SoundEffect>(TerraColpita_p).CreateInstance()
                };


            base.Initialize();
        }

        static public bool AudioState
        {
            get { return AudioManager.Volume == 1; }
            private set { }
        }

        

        public void resumeAllSounds()
        {
            resumeSoundList(yellow1);
            resumeSoundList(yellow2);
            resumeSoundList(blue1);
            resumeSoundList(blue2);
            resumeSoundList(green1);
            resumeSoundList(green2);
            resumeSoundList(click);
            resumeSoundList(playClick);
            resumeSoundList(BubbleWave);
            resumeSoundList(Defeat);
            resumeSoundList(brokenSack);
            resumeSoundList(Aspirapolvere);
            resumeSoundList(TrashMaster);
            resumeSoundList(Flick);
            resumeSoundList(error);
            resumeSoundList(No);
            resumeSoundList(TerraColpita);
            //resumeSoundList();
         
            if (soundTrack.State == SoundState.Paused)
                soundTrack.Resume();
        }

        public void pauseAllSounds()
        {
            pauseSoundList(yellow1);
            pauseSoundList(yellow2);
            pauseSoundList(blue1);
            pauseSoundList(blue2);
            pauseSoundList(green1);
            pauseSoundList(green2);
            pauseSoundList(click);
            pauseSoundList(playClick);
            pauseSoundList(BubbleWave);
            pauseSoundList(Defeat);
            pauseSoundList(brokenSack);
            pauseSoundList(Aspirapolvere);
            pauseSoundList(Flick);
            pauseSoundList(TrashMaster);
            pauseSoundList(error);
            pauseSoundList(No);
            pauseSoundList(TerraColpita);
                        
            if (soundTrack.State == SoundState.Playing)
                soundTrack.Pause();
        }
        
        public void stopAllSounds()
        {
            stopSoundList(yellow1);
            stopSoundList(yellow2);
            stopSoundList(blue1);
            stopSoundList(blue2);
            stopSoundList(green1);
            stopSoundList(green2);
            stopSoundList(click);
            stopSoundList(playClick);
            stopSoundList(BubbleWave);
            stopSoundList(Defeat);
            stopSoundList(brokenSack);
            stopSoundList(Aspirapolvere);
            stopSoundList(Flick);
            stopSoundList(TrashMaster);
            stopSoundList(error);
            stopSoundList(No);
            stopSoundList(TerraColpita);
            
            soundTrack.Stop();

        }

        public void OnaudioOff()
        {

            if (AudioManager.Volume > 0)
                volume = 0;
         
            audioOffSoundList(yellow1);
            audioOffSoundList(yellow2);
            audioOffSoundList(blue1);
            audioOffSoundList(blue2);
            audioOffSoundList(green1);
            audioOffSoundList(green2);
            audioOffSoundList(click);
            audioOffSoundList(playClick);
            audioOffSoundList(BubbleWave);
            audioOffSoundList(Defeat);
            audioOffSoundList(brokenSack);
            audioOffSoundList(Aspirapolvere);
            audioOffSoundList(Flick);
            audioOffSoundList(TrashMaster);
            audioOffSoundList(error);
            audioOffSoundList(No);
            audioOffSoundList(TerraColpita);
            
            soundTrack.Volume = 0;
        }

        public void OnaudioOn()
        {
            if (MediaPlayer.State == MediaState.Playing)
                return;

            if (AudioManager.Volume == 0)
                volume = 1;

            audioOnSoundList(yellow1);
            audioOnSoundList(yellow2);
            audioOnSoundList(blue1);
            audioOnSoundList(blue2);
            audioOnSoundList(green1);
            audioOnSoundList(green2);
            audioOnSoundList(click);
            audioOnSoundList(playClick);
            audioOnSoundList(BubbleWave);
            audioOnSoundList(Defeat);
            audioOnSoundList(brokenSack);
            audioOnSoundList(Aspirapolvere);
            audioOnSoundList(Flick);
            audioOnSoundList(TrashMaster);
            audioOnSoundList(error);
            audioOnSoundList(No);
            audioOnSoundList(TerraColpita);

            soundTrack.Volume = 1;

            
        }

        #region private methods
        private void resumeSoundList(ArrayList<SoundEffectInstance> sounds)
        {
            for (int i = 0; i < sounds.Count; i++)
            {
                if (sounds[i].State == SoundState.Paused)
                    sounds[i].Resume();
            }
        }
        private void pauseSoundList(ArrayList<SoundEffectInstance> sounds)
        {
            for (int i = 0; i < sounds.Count; i++)
            {
                if (sounds[i].State == SoundState.Playing)
                {
                    sounds[i].Pause();
                }
            }
        }
        private void stopSoundList(ArrayList<SoundEffectInstance> sounds)
        {
            for (int i = 0; i < sounds.Count; i++)
            {
                sounds[i].Stop();
            }

        }
        private void audioOffSoundList(ArrayList<SoundEffectInstance> sounds)
        {
            for (int i = 0; i < sounds.Count; i++)
            {
                sounds[i].Volume = 0;
            }
        }
        private void audioOnSoundList(ArrayList<SoundEffectInstance> sounds)
        {
            for (int i = 0; i < sounds.Count; i++)
            {
                sounds[i].Volume = 1;
            }
        }

        #endregion

        protected override void Dispose(bool disposing)
        {
            Game.Services.RemoveService(typeof(IAudioManager));
            base.Dispose(disposing);
        }

        #region old stuff
        //public void OnWarp(float volume)
        //{
        //    PlaySoundEffectInstance(BubbleWave, volume, 0.0f, 0.0f, warp_p);
        //}

        //public void OnNukeExplode(float volume)
        //{
        //    for (int i = 0; i < playClick.Count; i++)
        //    {
        //        if (playClick[i].State != SoundState.Playing)
        //        {
        //            playClick[i].Pan = 0.0f;
        //            playClick[i].Pitch = 0.0f;

        //            playClick[i].Volume = (AudioManager.Volume / volume);
        //            playClick[i].Play();
        //            return;
        //        }
        //    }
        //    //PlaySoundEffectInstance(nuke_expl, 0.0f, 0.0f, nuke_expl_p);
        //}

        //public void OnPlasmaExplode()
        //{

        //    PlaySoundEffectInstance(green1, 0.0f, 0.0f, green1_p);
        //}

        //public void OnNukeLaunch()
        //{
        //    PlaySoundEffectInstance(click, 0.0f, 0.0f, click_p);
        //}

        //public void OnPlasmaShoot()
        //{
        //    PlaySoundEffectInstance(yellow1, 0.0f, 0.0f, yellow1_p);
        //}

        //public void OnProjectileShoot()
        //{
        //    PlaySoundEffectInstance(yellow2, 2.0f, 0, 0, yellow2_p);
        //}

        //public void OnLightningShoot()
        //{
        //    PlaySoundEffectInstance(blue1, 2.0f, 0, 0, blue1_p);
        //}

        //public void OnLaserShoot()
        //{
        //    PlaySoundEffectInstance(green2, 3.0f, 0, 0, green2_p);
        //}

        //public void OnShockwaveShoot(float volume)
        //{

        //    PlaySoundEffectInstance(green1, volume, 0, 0, green1_p);
        //}

        //public void OnSlowMotionBegin()
        //{
        //    for (int i = 0; i < Defeat.Count; i++)
        //    {
        //        Defeat[i].Stop();
        //    }
        //    Defeat.Clear();

        //    PlaySoundEffectInstance(Defeat, 0, 0, Defeat_p);
        //}

        //public void OnBepBegin(float volume)
        //{
        //    PlaySoundEffectInstance(warp, volume, 0, 0, warp_p);
        //}

        //public void OnbepBegin(float volume)
        //{
        //    for (int i = 0; i < warp.Count; i++)
        //    {
        //        warp[i].Stop();
        //    }
        //    warp.Clear();
        //    PlaySoundEffectInstance(warp, volume, 0, 0, warp_p);
        //}

        //public void OnFlashBegin()
        //{
        //    for (int i = 0; i < warp.Count; i++)
        //    {
        //        warp[i].Stop();
        //    }
        //    warp.Clear();
        //    for (int i = 0; i < Aspirapolvere.Count; i++)
        //    {
        //        Aspirapolvere[i].Stop();
        //    }
        //    Aspirapolvere.Clear();

        //    PlaySoundEffectInstance(Aspirapolvere, 0, 0, Aspirapolvere_p);
        //}

        //public void OnMusicaBaseBegin(float volume)
        //{
        //    soundTrack.IsLooped = true;
        //    soundTrack.Play();
        //}
        ////public void OnMusicaIntermediaBegin(float volume)
        ////{
        ////    for (int i = 0; i < bep.Count; i++)
        ////    {
        ////        bep[i].Stop();
        ////    }
        ////    PlaySoundEffectInstance(musica_intermedia, volume, 0, 0, musica_intermedia_p, true);
        ////}
        ////public void OnMusicaDinamicaBegin(float volume)
        ////{
        ////    for (int i = 0; i < musica_intermedia.Count; i++)
        ////    {
        ////        musica_intermedia[i].Stop();
        ////    }
        ////    PlaySoundEffectInstance(flash_effect, volume, 0, 0, musica_dinamica_p, true);
        ////}
        //private void PlaySoundEffectInstance(ArrayList<SoundEffectInstance> effect_list, float pitch, float pan, string path)
        //{


        //    for (int i = 0; i < effect_list.Count; i++)
        //    {
        //        if (!(effect_list[i].State == SoundState.Playing))
        //        {
        //            effect_list[i].Pitch = pitch;
        //            effect_list[i].Pitch = pan;
        //            effect_list[i].Volume = AudioManager.Volume;
        //            effect_list[i].Play();
        //            return;
        //        }
        //    }


        //    if (effect_list.Count == 3)
        //    {
        //        effect_list[0].Stop();
        //        effect_list.RemoveAt(0);
        //    }

        //    effect_list.Add(Game.Content.Load<SoundEffect>(path).CreateInstance());
        //    PlaySoundEffectInstance(effect_list, pitch, pan, path);
        //}


        //private void PlaySoundEffectInstance(ArrayList<SoundEffectInstance> effect_list, float volume_div, float pitch, float pan, string path)
        //{


        //    for (int i = 0; i < effect_list.Count; i++)
        //    {
        //        if (!(effect_list[i].State == SoundState.Playing))
        //        {
        //            effect_list[i].Pitch = pitch;
        //            effect_list[i].Pitch = pan;
        //            effect_list[i].Volume = (AudioManager.Volume / volume_div);
        //            effect_list[i].Play();
        //            return;
        //        }
        //    }

        //    if (effect_list.Count == 3)
        //    {
        //        effect_list[0].Stop();
        //        effect_list.RemoveAt(0);
        //    }

        //    effect_list.Add(Game.Content.Load<SoundEffect>(path).CreateInstance());
        //    PlaySoundEffectInstance(effect_list, volume_div, pitch, pan, path);
        //}
        //private void PlaySoundEffectInstance(ArrayList<SoundEffectInstance> effect_list, float volume_div, float pitch, float pan, string path, bool repeat)
        //{
        //    for (int i = 0; i < effect_list.Count; i++)
        //    {
        //        if (!(effect_list[i].State == SoundState.Playing))
        //        {
        //            effect_list[i].Pitch = pitch;
        //            effect_list[i].Pitch = pan;
        //            effect_list[i].Volume = (AudioManager.Volume / volume_div);
        //            effect_list[i].IsLooped = repeat;
        //            effect_list[i].Play();
        //            return;
        //        }
        //    }

        //    if (effect_list.Count == 3)
        //    {
        //        effect_list[0].Stop();
        //        effect_list.RemoveAt(0);
        //    }

        //    effect_list.Add(Game.Content.Load<SoundEffect>(path).CreateInstance());
        //    PlaySoundEffectInstance(effect_list, volume_div, pitch, pan, path, repeat);
        //}
        #endregion

        private void PlaySoundEffectInstance(ArrayList<SoundEffectInstance> Sounds, float Volume)
        {
            for (int i = 0; i < Sounds.Count; i++)
            {
                if (Sounds[i].State == SoundState.Stopped)
                {
                    Sounds[i].Volume = AudioManager.Volume / MathHelper.Clamp(Volume, 0.1f, 1);
                    Sounds[i].Play();
                    break;
                }
            }
        }

        public void OnYellow1(float volume)
        {
            PlaySoundEffectInstance(yellow1, volume);
        }

        public void OnYellow2(float volume)
        {
            PlaySoundEffectInstance(yellow2, volume);
        }

        public void OnBlue1(float volume)
        {
            PlaySoundEffectInstance(blue1, volume);
        }

        public void OnBlue2(float volume)
        {
            PlaySoundEffectInstance(blue2, volume);
        }

        public void OnGreen1(float volume)
        {
            PlaySoundEffectInstance(green1, volume);
        }

        public void OnGreen2(float volume)
        {
            PlaySoundEffectInstance(green2, volume);
        }

        public void OnClick(float volume)
        {
            PlaySoundEffectInstance(click, volume);
        }

        public void OnPlayClick(float volume)
        {
            PlaySoundEffectInstance(playClick, volume);
        }

        public void OnBubbleWave(float volume)
        {
            PlaySoundEffectInstance(BubbleWave, volume);
        }

        public void OnDefeat(float volume)
        {
            PlaySoundEffectInstance(Defeat, volume);
        }

        public void OnTrashMaster(float volume)
        {
            PlaySoundEffectInstance(TrashMaster, volume);
        }

        public void OnAspirapolvere(float volume)
        {
            PlaySoundEffectInstance(Aspirapolvere, volume);
        }

        public void OnError(float volume)
        {
            PlaySoundEffectInstance(error, volume);
        }

        public void OnBrokenSack(float volume)
        {
            PlaySoundEffectInstance(brokenSack, volume);
        }

        public void OnFlick(float volume)
        {
            PlaySoundEffectInstance(Flick, volume);
        }

        public void OnNo(float volume)
        {
            PlaySoundEffectInstance(No, volume);
        }

        public void OnTerraColpita(float volume)
        {
            PlaySoundEffectInstance(TerraColpita, volume);
        }

        public void OnSoundTrackBegin(float volume)
        {
            if (soundTrack.State == SoundState.Stopped)
            {
                soundTrack.Volume = AudioManager.Volume / MathHelper.Clamp(Volume, 0.1f, 1);
                soundTrack.IsLooped = true;
                soundTrack.Play();
            }
        }
    }
}
